/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <cstdint>
#include <memory>

#include "gtest/gtest.h"

#include "base/geometry/ng/size_t.h"
#include "base/geometry/offset.h"
#include "base/utils/utils.h"
#define private public
#include "core/components_ng/base/view_stack_processor.h"
#include "core/components_ng/pattern/grid/grid_item_model_ng.h"
#include "core/components_ng/pattern/grid/grid_item_pattern.h"
#include "core/components_ng/pattern/grid/grid_model_ng.h"
#include "core/components_ng/pattern/grid/grid_pattern.h"
#include "core/pipeline/base/constants.h"

using namespace testing;
using namespace testing::ext;

namespace OHOS::Ace::NG {
namespace {
constexpr float DEVICE_WIDTH = 720.0f;
constexpr float DEVICE_HEIGHT = 1136.0f;
constexpr float GRID_POSITION = 100.0f;
constexpr float GRID_DURATION = 200.0f;
constexpr int32_t GRID_MAX_COUNT = 10;
constexpr int32_t GRID_MIN_COUNT = 1;
constexpr int32_t GRID_CELL_LENGTH = 200;
constexpr float GRID_SCROLL_OFFSET = 1.0f;
const SizeF CONTAINER_SIZE(DEVICE_WIDTH, DEVICE_HEIGHT);
const Dimension GRID_COLUMNS_GAP = Dimension(10, DimensionUnit::PX);
const Dimension GRID_ROWS_GAP = Dimension(5, DimensionUnit::PX);
const std::string GRID_DIRECTION_ROW = "GridDirection.Row";
const std::string GRID_DIRECTION_ROW_REVERSE = "GridDirection.RowReverse";
const std::string GRID_DIRECTION_COLUMN = "GridDirection.Column";
const std::string GRID_DIRECTION_COLUMN_REVERSE = "GridDirection.ColumnReverse";
const std::string GRID_SCROLL_BAR_AUTO = "BarState.Auto";
const std::string GRID_SCROLL_BAR_OFF = "BarState.Off";
const std::string GRID_SCROLL_BAR_ON = "BarState.On";
const std::string GRID_TEMPLATE_ILLEGAL = "abcd1234 *&^%$";
const int32_t GRID_CACHED_COUNT = 5;
const std::string SCROLL_BAR_WIDTH = "10px";
const std::string SCROLL_BAR_COLOR = "#909090";
} // namespace

struct GridTestProperty {
    std::optional<std::string> rowsTemplate;
    std::optional<std::string> columnsTemplate;
    std::optional<Dimension> rowsGap;
    std::optional<Dimension> columnsGap;
    std::optional<int32_t> cachedCount;
    std::optional<FlexDirection> gridDirection;
    std::optional<int32_t> maxCount;
    std::optional<int32_t> minCount;
    std::optional<int32_t> cellLength;
    std::optional<bool> editable;
    std::optional<int32_t> scrollBarMode;
    std::optional<std::string> scrollBarWidth;
    std::optional<std::string> scrollBarColor;
};

class GridPatternTestNg : public testing::Test {
public:
    static RefPtr<FrameNode> CreateGrid(
        const GridTestProperty& gridTestProperty, const int32_t girdItemCount = 0);
};

RefPtr<FrameNode> GridPatternTestNg::CreateGrid(
    const GridTestProperty& gridTestProperty, const int32_t girdItemCount)
{
    GridModelNG grid;
    RefPtr<ScrollControllerBase> positionController = grid.CreatePositionController();
    RefPtr<ScrollProxy> scrollBarProxy = grid.CreateScrollBarProxy();
    grid.Create(positionController, scrollBarProxy);

    if (gridTestProperty.rowsTemplate.has_value()) {
        grid.SetRowsTemplate(gridTestProperty.rowsTemplate.value());
    }
    if (gridTestProperty.columnsTemplate.has_value()) {
        grid.SetColumnsTemplate(gridTestProperty.columnsTemplate.value());
    }
    if (gridTestProperty.rowsGap.has_value()) {
        grid.SetRowsGap(gridTestProperty.rowsGap.value());
    }
    if (gridTestProperty.columnsGap.has_value()) {
        grid.SetColumnsGap(gridTestProperty.columnsGap.value());
    }
    if (gridTestProperty.cachedCount.has_value()) {
        grid.SetCachedCount(gridTestProperty.cachedCount.value());
    }
    if (gridTestProperty.gridDirection.has_value()) {
        grid.SetLayoutDirection(gridTestProperty.gridDirection.value());
    }
    if (gridTestProperty.maxCount.has_value()) {
        grid.SetMaxCount(gridTestProperty.maxCount.value());
    }
    if (gridTestProperty.minCount.has_value()) {
        grid.SetMinCount(gridTestProperty.minCount.value());
    }
    if (gridTestProperty.cellLength.has_value()) {
        grid.SetCellLength(gridTestProperty.cellLength.value());
    }
    if (gridTestProperty.editable.has_value()) {
        grid.SetEditable(gridTestProperty.editable.value());
    }
    if (gridTestProperty.scrollBarMode.has_value()) {
        grid.SetScrollBarMode(gridTestProperty.scrollBarMode.value());
    }
    if (gridTestProperty.scrollBarWidth.has_value()) {
        grid.SetScrollBarWidth(gridTestProperty.scrollBarWidth.value());
    }
    if (gridTestProperty.scrollBarColor.has_value()) {
        grid.SetScrollBarColor(gridTestProperty.scrollBarColor.value());
    }

    GridItemModelNG gridItem;
    for (int32_t i = 0; i < girdItemCount; ++i) {
        gridItem.Create();
        ViewStackProcessor::GetInstance()->Pop();
    }

    RefPtr<UINode> element = ViewStackProcessor::GetInstance()->Finish();
    return AceType::DynamicCast<FrameNode>(element);
}

/**
 * @tc.name: GridTest001
 * @tc.desc: Fill all items to grid with fixed row and column
 * @tc.type: FUNC
 */
HWTEST_F(GridPatternTestNg, GridTest001, TestSize.Level1)
{
    /**
     * @tc.steps: step1. Set grid properties.
    */
    GridTestProperty gridTestProperty;
    gridTestProperty.rowsTemplate = std::make_optional("1fr 1fr 1fr");
    gridTestProperty.columnsTemplate = std::make_optional("1fr 1fr 1fr");

    /**
     * @tc.steps: step2. Create grid and gridItem.
    */
    const int32_t gridItemCount = 9;
    RefPtr<FrameNode> frameNode = CreateGrid(gridTestProperty, gridItemCount);
    ASSERT_NE(frameNode, nullptr);

    /**
     * @tc.steps: step3. Set layoutConstraint.
     * @tc.expected: step3. related function is called.
     */
    auto layoutWrapper = frameNode->CreateLayoutWrapper();
    ASSERT_NE(frameNode, nullptr);
    OptionalSizeF size(800.0f, 800.0f);
    LayoutConstraintF constraint;
    constraint.UpdateIllegalSelfIdealSizeWithCheck(size);
    layoutWrapper->Measure(constraint);
    layoutWrapper->Layout();

    /**
     * @tc.steps: step4. When setting fixed rows and columns, check the status of child nodes in the grid.
     * @tc.expected: step4. All child nodes are active.
     */
    for (int32_t i = 0; i < gridItemCount; ++i) {
        EXPECT_TRUE(layoutWrapper->GetOrCreateChildByIndex(i, false)->IsActive());
    }
}

/**
 * @tc.name: GridTest002
 * @tc.desc: Set fixed columns only Fill all items in the grid.
 * @tc.type: FUNC
 */
HWTEST_F(GridPatternTestNg, GridTest002, TestSize.Level1)
{
    /**
     * @tc.steps: step1. Set grid properties.
     */
    GridTestProperty gridTestProperty;
    gridTestProperty.columnsTemplate = std::make_optional("1fr 1fr");
    gridTestProperty.columnsGap = std::make_optional(GRID_COLUMNS_GAP);

    /**
     * @tc.steps: step2. Create grid and gridItem.
    */
    RefPtr<FrameNode> frameNode = CreateGrid(gridTestProperty, 10);
    ASSERT_NE(frameNode, nullptr);
    auto pattern = frameNode->GetPattern<GridPattern>();
    ASSERT_NE(pattern, nullptr);
    pattern->SetMultiSelectable(true);

    /**
     * @tc.steps: step3. Set layoutConstraint.
     * @tc.expected: step3. related function is called.
     */
    auto layoutWrapper = frameNode->CreateLayoutWrapper();
    ASSERT_NE(layoutWrapper, nullptr);
    LayoutConstraintF constraint;
    constraint.selfIdealSize.SetSize(CONTAINER_SIZE);

    /**
     * @tc.steps: step4. Call the measure and layout function of grid to calculate the size and layout.
     * @tc.expected: step4. Check size after layout.
     */
    layoutWrapper->Measure(constraint);
    layoutWrapper->Layout();
    EXPECT_EQ(layoutWrapper->GetGeometryNode()->GetFrameSize(), CONTAINER_SIZE);

    /**
     * @tc.steps: step5. Set different MouseInfo to verify the HandleMouseEventWithoutKeyboard function.
     * @tc.expected: step5. Check whether relevant parameters are correct.
     */
    MouseInfo info;
    info.SetButton(MouseButton::LEFT_BUTTON);
    info.SetAction(MouseAction::PRESS);
    const Offset offset1(20.0, 25.0);
    info.SetLocalLocation(offset1);

    pattern->HandleMouseEventWithoutKeyboard(info);
    EXPECT_EQ(pattern->mouseStartOffset_, OffsetF(info.GetLocalLocation().GetX(), info.GetLocalLocation().GetY()));
    EXPECT_EQ(pattern->mouseEndOffset_, OffsetF(info.GetLocalLocation().GetX(), info.GetLocalLocation().GetY()));

    info.SetAction(MouseAction::MOVE);
    const Offset offset2(25.0, 20.0);
    info.SetLocalLocation(offset2);
    pattern->HandleMouseEventWithoutKeyboard(info);
    EXPECT_EQ(pattern->mouseEndOffset_, OffsetF(info.GetLocalLocation().GetX(), info.GetLocalLocation().GetY()));

    info.SetAction(MouseAction::RELEASE);
    const Offset offset3(20.0, 20.0);
    info.SetLocalLocation(offset3);
    pattern->HandleMouseEventWithoutKeyboard(info);
    EXPECT_EQ(pattern->mouseStartOffset_, OffsetF(0.0f, 0.0f));
    EXPECT_EQ(pattern->mouseEndOffset_, OffsetF(0.0f, 0.0f));

    /**
     * @tc.steps: step6. Set different KeyEvent to verify the OnKeyEvent function.
     * @tc.expected: step6. Check whether the return value is correct.
     */
    KeyEvent event;
    auto ret = pattern->OnKeyEvent(event);
    EXPECT_EQ(ret, false);
    event.action = KeyAction::DOWN;
    event.code = KeyCode::KEY_PAGE_DOWN;
    ret = pattern->OnKeyEvent(event);
    EXPECT_EQ(ret, false);
    event.code = KeyCode::KEY_PAGE_UP;
    ret = pattern->OnKeyEvent(event);
    EXPECT_EQ(ret, false);
    ret = pattern->HandleDirectionKey(event.code);
    EXPECT_EQ(ret, false);
}

/**
 * @tc.name: GridTest003
 * @tc.desc: Set fixed rows only Fill all items in the grid.
 * @tc.type: FUNC
 */
HWTEST_F(GridPatternTestNg, GridTest003, TestSize.Level1)
{
    /**
     * @tc.steps: step1. Set grid properties.
     */
    GridTestProperty gridTestProperty;
    gridTestProperty.rowsTemplate = std::make_optional("1fr 1fr");
    gridTestProperty.rowsGap = std::make_optional(GRID_ROWS_GAP);
    gridTestProperty.scrollBarColor = std::make_optional(SCROLL_BAR_COLOR);

    /**
     * @tc.steps: step2. Create grid and gridItem.
    */
    RefPtr<FrameNode> frameNode = CreateGrid(gridTestProperty, 10);
    ASSERT_NE(frameNode, nullptr);
    auto pattern = frameNode->GetPattern<GridPattern>();
    ASSERT_NE(pattern, nullptr);
    pattern->SetMultiSelectable(true);

    /**
     * @tc.steps: step3. Set layoutConstraint.
     * @tc.expected: step3. related function is called.
     */
    auto layoutWrapper = frameNode->CreateLayoutWrapper();
    LayoutConstraintF constraint;
    constraint.selfIdealSize.SetSize(CONTAINER_SIZE);

    /**
     * @tc.steps: step4. Call the measure and layout function of grid to calculate the size and layout.
     * @tc.expected: step4. Check size after layout.
     */
    layoutWrapper->Measure(constraint);
    layoutWrapper->Layout();
    EXPECT_EQ(layoutWrapper->GetGeometryNode()->GetFrameSize(), CONTAINER_SIZE);

    /**
     * @tc.steps: step5. Call OnModifyDone function.
     * @tc.expected: step5. Check whether the updated properties and parameters are correct.
     */
    pattern->OnModifyDone();
    EXPECT_TRUE(pattern->multiSelectable_);
    EXPECT_TRUE(pattern->isMouseEventInit_);
    EXPECT_TRUE(pattern->isConfigScrollable_);

    /**
     * @tc.steps: step5. Change MultiSelectable and Call OnModifyDone  function.
     * @tc.expected: step5. Check whether the updated properties and parameters are correct.
     */
    pattern->SetMultiSelectable(false);
    pattern->OnModifyDone();
    EXPECT_FALSE(pattern->multiSelectable_);
    EXPECT_FALSE(pattern->isMouseEventInit_);

    /**
     * @tc.steps: step6. Call the AddScrollEvent function to add a scroll position callback event.
     * @tc.expected: step6. Call and check the return value of the callback function.
     */
    pattern->AddScrollEvent();
    EXPECT_NE(pattern->scrollableEvent_, nullptr);
    auto callback = pattern->scrollableEvent_->GetScrollPositionCallback();
    EXPECT_NE(callback, nullptr);
    auto ret = callback(GRID_SCROLL_OFFSET, SCROLL_FROM_START);
    EXPECT_EQ(ret, true);

    /**
     * @tc.steps: step7. When isConfigScrollable_ is false, call related functions.
     * @tc.expected: step7. Check the return value of the related function.
     */
    pattern->isConfigScrollable_ = false;
    ret = pattern->AnimateTo(GRID_POSITION, GRID_DURATION, Curves::LINEAR);
    EXPECT_EQ(ret, false);
    ret = pattern->UpdateCurrentOffset(GRID_SCROLL_OFFSET, SCROLL_FROM_UPDATE);
    EXPECT_EQ(ret, false);
    ret = pattern->UpdateStartIndex(1.0);
    EXPECT_EQ(ret, false);

    /**
     * @tc.steps: step8. When isConfigScrollable_ is true, call AnimateTo functions.
     * @tc.expected: step8. Check the return value and related parameters.
     */
    pattern->ScrollPage(false);
    pattern->isConfigScrollable_ = true;
    ret = pattern->AnimateTo(GRID_POSITION, GRID_DURATION, Curves::LINEAR);
    EXPECT_NE(pattern->animator_, nullptr);
    EXPECT_EQ(ret, true);

    /**
     * @tc.steps: step9. When offsetEnd_ and reachStart_ are true, call OnScrollCallback functions.
     * @tc.expected: step9. Check whether the return value is correct.
     */
    pattern->gridLayoutInfo_.offsetEnd_ = true;
    pattern->gridLayoutInfo_.reachStart_ = true;
    ret = pattern->OnScrollCallback(0.0f, SCROLL_FROM_ANIMATION);
    EXPECT_EQ(ret, false);
    ret = pattern->OnScrollCallback(GRID_SCROLL_OFFSET, SCROLL_FROM_ANIMATION);
    EXPECT_EQ(pattern->gridLayoutInfo_.offsetEnd_, false);
    EXPECT_EQ(ret, false);
    ret = pattern->OnScrollCallback(-1.0f, SCROLL_FROM_ANIMATION);
    EXPECT_EQ(pattern->gridLayoutInfo_.reachStart_, false);
    EXPECT_EQ(ret, true);
}

/**
 * @tc.name: GridTest004
 * @tc.desc: When fixed rows and columns are not set and direction is row, all items in the grid are filled.
 * @tc.type: FUNC
 */
HWTEST_F(GridPatternTestNg, GridTest004, TestSize.Level1)
{
    /**
     * @tc.steps: step1. Set grid properties.
     */
    GridTestProperty gridTestProperty;
    gridTestProperty.columnsGap = std::make_optional(GRID_COLUMNS_GAP);
    gridTestProperty.rowsGap = std::make_optional(GRID_ROWS_GAP);
    gridTestProperty.gridDirection = std::make_optional(FlexDirection::ROW);
    gridTestProperty.maxCount = std::make_optional(GRID_MAX_COUNT);
    gridTestProperty.minCount = std::make_optional(GRID_MIN_COUNT);
    gridTestProperty.cellLength = std::make_optional(GRID_CELL_LENGTH);

    /**
     * @tc.steps: step2. Create grid and gridItem.
    */
    RefPtr<FrameNode> frameNode = CreateGrid(gridTestProperty, 10);
    ASSERT_NE(frameNode, nullptr);
    auto pattern = frameNode->GetPattern<GridPattern>();
    ASSERT_NE(pattern, nullptr);
    pattern->SetMultiSelectable(true);

    /**
     * @tc.steps: step3. Set layoutConstraint.
     * @tc.expected: step3. related function is called.
     */
    auto layoutWrapper = frameNode->CreateLayoutWrapper();
    LayoutConstraintF constraint;
    constraint.selfIdealSize.SetSize(CONTAINER_SIZE);

    /**
     * @tc.steps: step4. Call the measure and layout function of grid to calculate the size and layout.
     * @tc.expected: step4. Check size after layout.
     */
    layoutWrapper->Measure(constraint);
    layoutWrapper->Layout();
    EXPECT_EQ(layoutWrapper->GetGeometryNode()->GetFrameSize(), CONTAINER_SIZE);

    /**
     * @tc.steps: step5. Get grid layout properties.
     * @tc.expected: step5. Check whether the updated properties is correct.
     */
    auto layoutProperty = frameNode->GetLayoutProperty<GridLayoutProperty>();
    auto layoutDirectionStr = layoutProperty->GetGridDirectionStr();
    EXPECT_EQ(layoutDirectionStr, GRID_DIRECTION_ROW);

    /**
     * @tc.steps: step6. Get the pattern to call the related functions in the positionController.
     */
    EXPECT_NE(pattern->positionController_, nullptr);

    /**
     * @tc.steps: step7. When Axis is VERTICAL and ScrollEdgeType is SCROLL_TOP, call the related functions in
     * positionController.
     * @tc.expected: step7. Check whether the return value is correct.
     */
    pattern->gridLayoutInfo_.axis_ = Axis::VERTICAL;
    ScrollEdgeType scrollEdgeType = ScrollEdgeType::SCROLL_TOP;
    pattern->positionController_->ScrollToEdge(scrollEdgeType, true);
    pattern->positionController_->ScrollPage(true, true);
    auto axis = pattern->positionController_->GetScrollDirection();
    EXPECT_EQ(axis, Axis::VERTICAL);

    /**
     * @tc.steps: step8. When Axis is HORIZONTAL and ScrollEdgeType is SCROLL_RIGHT, call the related functions in
     * positionController.
     * @tc.expected: step8. Check whether the return value is correct.
     */
    pattern->gridLayoutInfo_.axis_ = Axis::HORIZONTAL;
    scrollEdgeType = ScrollEdgeType::SCROLL_RIGHT;
    pattern->positionController_->ScrollToEdge(scrollEdgeType, true);
    pattern->positionController_->ScrollPage(true, true);
    axis = pattern->positionController_->GetScrollDirection();
    EXPECT_EQ(axis, Axis::HORIZONTAL);

    /**
     * @tc.steps: step9. When Axis is NONE, call the related functions in positionController.
     * @tc.expected: step9. Check whether the return value is correct.
     */
    pattern->gridLayoutInfo_.axis_ = Axis::NONE;
    auto offset = pattern->positionController_->GetCurrentOffset();
    EXPECT_EQ(offset, Offset::Zero());
}

/**
 * @tc.name: GridTest005
 * @tc.desc: When fixed rows and columns are not set and direction is RowReverse, all items in the grid are filled.
 * @tc.type: FUNC
 */
HWTEST_F(GridPatternTestNg, GridTest005, TestSize.Level1)
{
    /**
     * @tc.steps: step1. Set grid properties.
     */
    GridTestProperty gridTestProperty;
    gridTestProperty.columnsGap = std::make_optional(GRID_COLUMNS_GAP);
    gridTestProperty.rowsGap = std::make_optional(GRID_ROWS_GAP);
    gridTestProperty.gridDirection = std::make_optional(FlexDirection::ROW_REVERSE);
    gridTestProperty.maxCount = std::make_optional(GRID_MAX_COUNT);
    gridTestProperty.minCount = std::make_optional(GRID_MIN_COUNT);
    gridTestProperty.cellLength = std::make_optional(GRID_CELL_LENGTH);
    gridTestProperty.scrollBarMode = std::make_optional(static_cast<int32_t>(NG::DisplayMode::AUTO));

    /**
     * @tc.steps: step2. Create grid and gridItem.
    */
    RefPtr<FrameNode> frameNode = CreateGrid(gridTestProperty, 10);
    ASSERT_NE(frameNode, nullptr);
    auto pattern = frameNode->GetPattern<GridPattern>();
    ASSERT_NE(pattern, nullptr);
    pattern->SetMultiSelectable(true);

    /**
     * @tc.steps: step3. Set layoutConstraint.
     * @tc.expected: step3. related function is called.
     */
    auto layoutWrapper = frameNode->CreateLayoutWrapper();
    LayoutConstraintF constraint;
    constraint.selfIdealSize.SetSize(CONTAINER_SIZE);

    /**
     * @tc.steps: step4. Call the measure and layout function of grid to calculate the size and layout.
     * @tc.expected: step4. Check size after layout.
     */
    layoutWrapper->Measure(constraint);
    layoutWrapper->Layout();
    EXPECT_EQ(layoutWrapper->GetGeometryNode()->GetFrameSize(), CONTAINER_SIZE);

    /**
     * @tc.steps: step5. Get grid layout properties.
     * @tc.expected: step5. Check whether the updated properties is correct.
     */
    auto layoutProperty = frameNode->GetLayoutProperty<GridLayoutProperty>();
    EXPECT_NE(layoutProperty, nullptr);
    auto layoutDirectionStr = layoutProperty->GetGridDirectionStr();
    EXPECT_EQ(layoutDirectionStr, GRID_DIRECTION_ROW_REVERSE);
}

/**
 * @tc.name: GridTest006
 * @tc.desc: When fixed rows and columns are not set and direction is Column, all items in the grid are filled.
 * @tc.type: FUNC
 */
HWTEST_F(GridPatternTestNg, GridTest006, TestSize.Level1)
{
    /**
     * @tc.steps: step1. Set grid properties.
     */
    GridTestProperty gridTestProperty;
    gridTestProperty.columnsGap = std::make_optional(GRID_COLUMNS_GAP);
    gridTestProperty.rowsGap = std::make_optional(GRID_ROWS_GAP);
    gridTestProperty.gridDirection = std::make_optional(FlexDirection::COLUMN);
    gridTestProperty.maxCount = std::make_optional(GRID_MAX_COUNT);
    gridTestProperty.minCount = std::make_optional(GRID_MIN_COUNT);
    gridTestProperty.cellLength = std::make_optional(GRID_CELL_LENGTH);
    gridTestProperty.scrollBarMode = std::make_optional(static_cast<int32_t>(NG::DisplayMode::ON));

    /**
     * @tc.steps: step2. Create grid and gridItem.
    */
    RefPtr<FrameNode> frameNode = CreateGrid(gridTestProperty, 10);
    ASSERT_NE(frameNode, nullptr);
    auto pattern = frameNode->GetPattern<GridPattern>();
    ASSERT_NE(pattern, nullptr);
    pattern->SetMultiSelectable(true);

    /**
     * @tc.steps: step3. Set layoutConstraint.
     * @tc.expected: step3. related function is called.
     */
    auto layoutWrapper = frameNode->CreateLayoutWrapper();
    LayoutConstraintF constraint;
    constraint.selfIdealSize.SetSize(CONTAINER_SIZE);

    /**
     * @tc.steps: step4. Call the measure and layout function of grid to calculate the size and layout.
     * @tc.expected: step4. Check size after layout.
     */
    layoutWrapper->Measure(constraint);
    layoutWrapper->Layout();
    EXPECT_EQ(layoutWrapper->GetGeometryNode()->GetFrameSize(), CONTAINER_SIZE);

    /**
     * @tc.steps: step5. Get grid layout properties.
     * @tc.expected: step5. Check whether the updated properties is correct.
     */
    auto layoutProperty = frameNode->GetLayoutProperty<GridLayoutProperty>();
    EXPECT_NE(layoutProperty, nullptr);
    auto layoutDirectionStr = layoutProperty->GetGridDirectionStr();
    EXPECT_EQ(layoutDirectionStr, GRID_DIRECTION_COLUMN);
}

/**
 * @tc.name: GridTest007
 * @tc.desc: When fixed rows and columns are not set and direction is ColumnReverse, all items in the grid are filled.
 * @tc.type: FUNC
 */
HWTEST_F(GridPatternTestNg, GridTest007, TestSize.Level1)
{
    /**
     * @tc.steps: step1. Set grid properties.
     */
    GridTestProperty gridTestProperty;
    gridTestProperty.columnsGap = std::make_optional(GRID_COLUMNS_GAP);
    gridTestProperty.rowsGap = std::make_optional(GRID_ROWS_GAP);
    gridTestProperty.gridDirection = std::make_optional(FlexDirection::COLUMN_REVERSE);
    gridTestProperty.maxCount = std::make_optional(GRID_MAX_COUNT);
    gridTestProperty.minCount = std::make_optional(GRID_MIN_COUNT);
    gridTestProperty.cellLength = std::make_optional(GRID_CELL_LENGTH);
    gridTestProperty.scrollBarMode = std::make_optional(static_cast<int32_t>(NG::DisplayMode::OFF));

    /**
     * @tc.steps: step2. Create grid and gridItem.
    */
    RefPtr<FrameNode> frameNode = CreateGrid(gridTestProperty, 10);
    ASSERT_NE(frameNode, nullptr);
    auto pattern = frameNode->GetPattern<GridPattern>();
    ASSERT_NE(pattern, nullptr);
    pattern->SetMultiSelectable(true);

    /**
     * @tc.steps: step3. Set layoutConstraint.
     * @tc.expected: step3. related function is called.
     */
    auto layoutWrapper = frameNode->CreateLayoutWrapper();
    LayoutConstraintF constraint;
    constraint.selfIdealSize.SetSize(CONTAINER_SIZE);

    /**
     * @tc.steps: step4. Call the measure and layout function of grid to calculate the size and layout.
     * @tc.expected: step4. Check size after layout.
     */
    layoutWrapper->Measure(constraint);
    layoutWrapper->Layout();
    EXPECT_EQ(layoutWrapper->GetGeometryNode()->GetFrameSize(), CONTAINER_SIZE);

    /**
     * @tc.steps: step5. Get grid layout properties.
     * @tc.expected: step5. Check whether the updated properties is correct.
     */
    auto layoutProperty = frameNode->GetLayoutProperty<GridLayoutProperty>();
    EXPECT_NE(layoutProperty, nullptr);
    auto layoutDirectionStr = layoutProperty->GetGridDirectionStr();
    EXPECT_EQ(layoutDirectionStr, GRID_DIRECTION_COLUMN_REVERSE);

    /**
     * @tc.steps: step6. Get grid EventHub to call related function.
     * @tc.expected: step6. Check whether the related parameters is correct.
     */
    auto eventHub = frameNode->GetEventHub<GridEventHub>();
    ASSERT_NE(eventHub, nullptr);
    GestureEvent info;
    info.globalPoint_.SetX(1.0f);
    info.globalPoint_.SetY(1.0f);
    eventHub->HandleOnItemDragStart(info);
    EXPECT_EQ(eventHub->draggedIndex_, 0);
    EXPECT_EQ(eventHub->dragDropProxy_, nullptr);
    eventHub->HandleOnItemDragUpdate(info);
    EXPECT_EQ(eventHub->draggedIndex_, 0);
    EXPECT_EQ(eventHub->dragDropProxy_, nullptr);
    eventHub->HandleOnItemDragEnd(info);
    EXPECT_EQ(eventHub->draggedIndex_, 0);
    EXPECT_EQ(eventHub->dragDropProxy_, nullptr);
    eventHub->HandleOnItemDragCancel();
    EXPECT_EQ(eventHub->draggedIndex_, 0);
    EXPECT_EQ(eventHub->dragDropProxy_, nullptr);
}

/**
 * @tc.name: GridTest008
 * @tc.desc: Set fixed rows only Fill all items in the grid.
 * @tc.type: FUNC
 */
HWTEST_F(GridPatternTestNg, GridTest008, TestSize.Level1)
{
    /**
     * @tc.steps: step1. Set grid properties.
     */
    GridTestProperty gridTestProperty;
    gridTestProperty.rowsTemplate = std::make_optional("1fr 2fr");
    gridTestProperty.rowsGap = std::make_optional(GRID_ROWS_GAP);
    gridTestProperty.editable = std::make_optional(true);

    /**
     * @tc.steps: step2. Create grid and gridItem.
    */
    RefPtr<FrameNode> frameNode = CreateGrid(gridTestProperty, 10);
    ASSERT_NE(frameNode, nullptr);
    auto pattern = frameNode->GetPattern<GridPattern>();
    ASSERT_NE(pattern, nullptr);
    pattern->SetMultiSelectable(true);

    /**
     * @tc.steps: step3. Set layoutConstraint.
     * @tc.expected: step3. related function is called.
     */
    auto layoutWrapper = frameNode->CreateLayoutWrapper();
    LayoutConstraintF constraint;
    constraint.selfIdealSize.SetSize(CONTAINER_SIZE);

    /**
     * @tc.steps: step4. Call the measure and layout function of grid to calculate the size and layout.
     * @tc.expected: step4. Check size after layout.
     */
    layoutWrapper->Measure(constraint);
    layoutWrapper->Layout();
    EXPECT_EQ(layoutWrapper->GetGeometryNode()->GetFrameSize(), CONTAINER_SIZE);

    /**
     * @tc.steps: step5. When setting different startOffset and endOffset, call the ComputeSelectedZone function.
     * @tc.expected: step5. Check whether the return value is correct.
     */
    OffsetF startOffset1(1.0f, 0.0f);
    OffsetF endOffset1(1.0f, 0.0f);
    auto selectedZone1 = pattern->ComputeSelectedZone(startOffset1, endOffset1);
    EXPECT_EQ(selectedZone1, RectF(startOffset1.GetX(), startOffset1.GetY(), endOffset1.GetX() - startOffset1.GetX(),
                                 endOffset1.GetY() - startOffset1.GetY()));

    OffsetF startOffset2(1.0f, 1.0f);
    OffsetF endOffset2(1.0f, 0.0f);
    auto selectedZone2 = pattern->ComputeSelectedZone(startOffset2, endOffset2);
    EXPECT_EQ(selectedZone2, RectF(startOffset2.GetX(), endOffset2.GetY(), endOffset2.GetX() - startOffset2.GetX(),
                                 startOffset2.GetY() - endOffset2.GetY()));

    OffsetF startOffset3(1.0f, 0.0f);
    OffsetF endOffset3(0.0f, 1.0f);
    auto selectedZone3 = pattern->ComputeSelectedZone(startOffset3, endOffset3);
    EXPECT_EQ(selectedZone3, RectF(endOffset3.GetX(), startOffset3.GetY(), startOffset3.GetX() - endOffset3.GetX(),
                                 endOffset3.GetY() - startOffset3.GetY()));

    OffsetF startOffset4(1.0f, 1.0f);
    OffsetF endOffset4(0.0f, 0.0f);
    auto selectedZone4 = pattern->ComputeSelectedZone(startOffset4, endOffset4);
    EXPECT_EQ(selectedZone4, RectF(endOffset4.GetX(), endOffset4.GetY(), startOffset4.GetX() - endOffset4.GetX(),
                                 startOffset4.GetY() - endOffset4.GetY()));
}

RefPtr<FrameNode> TestScrollGrid(OptionalSizeF gridSize, double gridItemHeight, int32_t gridItemFrom,
    int32_t gridItemTo, float scrollOffset = 0.0f, int32_t totalItemCount = 9)
{
    /**
     * @tc.steps: step1. Create grid node and initialize width, height, properties.
     */
    GridModelNG grid;
    RefPtr<V2::GridPositionController> positionController;
    RefPtr<ScrollProxy> scrollBarProxy = grid.CreateScrollBarProxy();
    grid.Create(positionController, scrollBarProxy);
    grid.SetColumnsTemplate("1fr 1fr 1fr");

    /**
     * @tc.steps: step2. Create the child nodes gridItem of the grid.
     */
    GridItemModelNG gridItem;
    for (int32_t i = 0; i < totalItemCount; ++i) {
        gridItem.Create();
        auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
        CHECK_NULL_RETURN(frameNode, nullptr);
        auto layoutProperty = frameNode->GetLayoutProperty();
        CHECK_NULL_RETURN(layoutProperty, frameNode);
        layoutProperty->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, NG::CalcLength(Dimension(gridItemHeight))));
        ViewStackProcessor::GetInstance()->Pop();
    }

    /**
     * @tc.steps: step3. Get grid frameNode and set layoutConstraint.
     * @tc.expected: step3. related function is called.
     */
    auto frameNode = AceType::DynamicCast<FrameNode>(ViewStackProcessor::GetInstance()->Finish());
    EXPECT_FALSE(frameNode == nullptr);
    auto layoutWrapper = frameNode->CreateLayoutWrapper();
    LayoutConstraintF constraint;
    constraint.UpdateIllegalSelfIdealSizeWithCheck(gridSize);

    /**
     * @tc.steps: step4. Call the measure and layout function of grid to calculate the size and layout.
     */
    layoutWrapper->Measure(constraint);
    layoutWrapper->Layout();

    // scroll
    if (!NearZero(scrollOffset)) {
        auto gridPattern = frameNode->GetPattern<GridPattern>();
        EXPECT_FALSE(gridPattern == nullptr);
        gridPattern->UpdateCurrentOffset(scrollOffset, SCROLL_FROM_UPDATE);
        layoutWrapper = frameNode->CreateLayoutWrapper();
        LayoutConstraintF constraint;
        constraint.UpdateIllegalSelfIdealSizeWithCheck(gridSize);
        layoutWrapper->Measure(constraint);
        layoutWrapper->Layout();

        // save current grid info to grid pattern for next operation
        DirtySwapConfig config { false, false, false, false };
        auto layoutAlgorithmWrapper = AceType::DynamicCast<LayoutAlgorithmWrapper>(layoutWrapper->GetLayoutAlgorithm());
        CHECK_NULL_RETURN(layoutAlgorithmWrapper, frameNode);
        config.skipMeasure = layoutAlgorithmWrapper->SkipMeasure() || layoutWrapper->SkipMeasureContent();
        config.skipLayout = layoutAlgorithmWrapper->SkipLayout();
        gridPattern->OnDirtyLayoutWrapperSwap(layoutWrapper, config);
    }
    /**
     * @tc.steps: step5. When setting fixed rows and columns, check the status of child nodes in the grid.
     * @tc.expected: step3. All child nodes are active.
     */
    for (int32_t i = gridItemFrom; i < gridItemTo; ++i) {
        EXPECT_TRUE(layoutWrapper->GetOrCreateChildByIndex(i, false)->IsActive());
    }

    return frameNode;
}

/**
 * @tc.name: GridTest009
 * @tc.desc: grid with fixed column
 * @tc.type: FUNC
 */
HWTEST_F(GridPatternTestNg, GridTest009, TestSize.Level1)
{
    OptionalSizeF gridSize(900.0f, 900.0f);
    const int32_t itemCount = 9;
    constexpr double gridItemHeight = 300.0f;
    TestScrollGrid(gridSize, gridItemHeight, 0, itemCount);
}

/**
 * @tc.name: GridTest010
 * @tc.desc: grid with fixed column, some griditem not show
 * @tc.type: FUNC
 */
HWTEST_F(GridPatternTestNg, GridTest010, TestSize.Level1)
{
    OptionalSizeF gridSize(900.0f, 600.0f);
    const int32_t itemCount = 6;
    constexpr double gridItemHeight = 300.0f;
    TestScrollGrid(gridSize, gridItemHeight, 0, itemCount);
}

/**
 * @tc.name: GridTest011
 * @tc.desc: grid with fixed column, some griditem not fully show
 * @tc.type: FUNC
 */
HWTEST_F(GridPatternTestNg, GridTest011, TestSize.Level1)
{
    OptionalSizeF gridSize(900.0f, 800.0f);
    const int32_t itemCount = 9;
    constexpr double gridItemHeight = 300.0f;
    TestScrollGrid(gridSize, gridItemHeight, 0, itemCount);
}

/**
 * @tc.name: GridTest012
 * @tc.desc: grid with fixed column, scroll to show one more line
 * @tc.type: FUNC
 */
HWTEST_F(GridPatternTestNg, GridTest012, TestSize.Level1)
{
    OptionalSizeF gridSize(900.0f, 600.0f);
    const int32_t itemCount = 9;
    constexpr double gridItemHeight = 300.0f;
    TestScrollGrid(gridSize, gridItemHeight, 0, itemCount, -100.0f);
}

/**
 * @tc.name: GridTest013
 * @tc.desc: grid with fixed column, scroll to end
 * @tc.type: FUNC
 */
HWTEST_F(GridPatternTestNg, GridTest013, TestSize.Level1)
{
    OptionalSizeF gridSize(900.0f, 600.0f);
    const int32_t itemCount = 9;
    constexpr double gridItemHeight = 300.0f;
    TestScrollGrid(gridSize, gridItemHeight, 3, itemCount, -300.0f);
}

/**
 * @tc.name: GridTest014
 * @tc.desc: grid with fixed column, scroll to index not fully showed at last line
 * @tc.type: FUNC
 */
HWTEST_F(GridPatternTestNg, GridTest014, TestSize.Level1)
{
    OptionalSizeF gridSize(900.0f, 600.0f);
    const int32_t itemCount = 9;
    constexpr double gridItemHeight = 300.0f;
    auto frameNode = TestScrollGrid(gridSize, gridItemHeight, 0, itemCount, -100.0f);
    EXPECT_FALSE(frameNode == nullptr);
    auto gridPattern = frameNode->GetPattern<GridPattern>();
    EXPECT_FALSE(gridPattern == nullptr);
    gridPattern->UpdateStartIndex(8);
    auto layoutWrapper = frameNode->CreateLayoutWrapper();
    LayoutConstraintF constraint;
    constraint.UpdateIllegalSelfIdealSizeWithCheck(gridSize);
    layoutWrapper->Measure(constraint);
    layoutWrapper->Layout();
    for (int32_t i = 0; i < 3; ++i) {
        EXPECT_FALSE(layoutWrapper->GetOrCreateChildByIndex(i, false)->IsActive());
    }
}

/**
 * @tc.name: GridTest015
 * @tc.desc: grid with fixed column, scroll to index not fully showed at first line
 * @tc.type: FUNC
 */
HWTEST_F(GridPatternTestNg, GridTest015, TestSize.Level1)
{
    OptionalSizeF gridSize(900.0f, 600.0f);
    const int32_t itemCount = 9;
    constexpr double gridItemHeight = 300.0f;
    auto frameNode = TestScrollGrid(gridSize, gridItemHeight, 0, itemCount, -100.0f);
    EXPECT_FALSE(frameNode == nullptr);
    auto gridPattern = frameNode->GetPattern<GridPattern>();
    EXPECT_FALSE(gridPattern == nullptr);
    gridPattern->UpdateStartIndex(1);
    auto layoutWrapper = frameNode->CreateLayoutWrapper();
    LayoutConstraintF constraint;
    constraint.UpdateIllegalSelfIdealSizeWithCheck(gridSize);
    layoutWrapper->Measure(constraint);
    layoutWrapper->Layout();
    for (int32_t i = 6; i < itemCount; ++i) {
        EXPECT_FALSE(layoutWrapper->GetOrCreateChildByIndex(i, false)->IsActive());
    }
}

/**
 * @tc.name: GridTest016
 * @tc.desc: grid with fixed column, scroll to index fully showed
 * @tc.type: FUNC
 */
HWTEST_F(GridPatternTestNg, GridTest016, TestSize.Level1)
{
    OptionalSizeF gridSize(900.0f, 600.0f);
    const int32_t itemCount = 9;
    constexpr double gridItemHeight = 300.0f;
    auto frameNode = TestScrollGrid(gridSize, gridItemHeight, 0, itemCount, -100.0f);
    EXPECT_FALSE(frameNode == nullptr);
    auto gridPattern = frameNode->GetPattern<GridPattern>();
    EXPECT_FALSE(gridPattern == nullptr);
    gridPattern->UpdateStartIndex(3);
    auto layoutWrapper = frameNode->CreateLayoutWrapper();
    LayoutConstraintF constraint;
    constraint.UpdateIllegalSelfIdealSizeWithCheck(gridSize);
    layoutWrapper->Measure(constraint);
    layoutWrapper->Layout();
    for (int32_t i = 0; i < itemCount; ++i) {
        EXPECT_TRUE(layoutWrapper->GetOrCreateChildByIndex(i, false)->IsActive());
    }
}

/**
 * @tc.name: GridTest017
 * @tc.desc: grid with fixed column, scroll to index not fully showed at last line
 * @tc.type: FUNC
 */
HWTEST_F(GridPatternTestNg, GridTest017, TestSize.Level1)
{
    OptionalSizeF gridSize(900.0f, 600.0f);
    const int32_t itemCount = 9;
    constexpr double gridItemHeight = 300.0f;
    auto frameNode = TestScrollGrid(gridSize, gridItemHeight, 0, itemCount, -100.0f, 10);
    EXPECT_FALSE(frameNode == nullptr);
    auto gridPattern = frameNode->GetPattern<GridPattern>();
    EXPECT_FALSE(gridPattern == nullptr);
    gridPattern->UpdateStartIndex(8);
    auto layoutWrapper = frameNode->CreateLayoutWrapper();
    LayoutConstraintF constraint;
    constraint.UpdateIllegalSelfIdealSizeWithCheck(gridSize);
    layoutWrapper->Measure(constraint);
    layoutWrapper->Layout();
    EXPECT_FALSE(layoutWrapper->GetOrCreateChildByIndex(9, false)->IsActive());
}

/**
 * @tc.name: GridTest018
 * @tc.desc: grid with fixed column, scroll to index out of view
 * @tc.type: FUNC
 */
HWTEST_F(GridPatternTestNg, GridTest018, TestSize.Level1)
{
    OptionalSizeF gridSize(900.0f, 600.0f);
    const int32_t itemCount = 9;
    constexpr double gridItemHeight = 300.0f;
    // scroll to show index 0-8
    auto frameNode = TestScrollGrid(gridSize, gridItemHeight, 0, itemCount, -100.0f, 10);

    // scroll to index 9
    EXPECT_FALSE(frameNode == nullptr);
    auto gridPattern = frameNode->GetPattern<GridPattern>();
    EXPECT_FALSE(gridPattern == nullptr);
    gridPattern->UpdateStartIndex(9);
    auto layoutWrapper = frameNode->CreateLayoutWrapper();
    LayoutConstraintF constraint;
    constraint.UpdateIllegalSelfIdealSizeWithCheck(gridSize);
    layoutWrapper->Measure(constraint);
    layoutWrapper->Layout();
    EXPECT_TRUE(layoutWrapper->GetOrCreateChildByIndex(9, false)->IsActive());
    EXPECT_FALSE(layoutWrapper->GetOrCreateChildByIndex(0, false)->IsActive());

    // save current grid info to grid pattern for next operation
    DirtySwapConfig config { false, false, false, false };
    auto layoutAlgorithmWrapper = layoutWrapper->GetLayoutAlgorithm();
    CHECK_NULL_VOID(layoutAlgorithmWrapper);
    config.skipMeasure = layoutAlgorithmWrapper->SkipMeasure() || layoutWrapper->SkipMeasureContent();
    config.skipLayout = layoutAlgorithmWrapper->SkipLayout();
    gridPattern->OnDirtyLayoutWrapperSwap(layoutWrapper, config);

    // scroll to index 0
    gridPattern->UpdateStartIndex(0);
    layoutWrapper = frameNode->CreateLayoutWrapper();
    layoutWrapper->Measure(constraint);
    layoutWrapper->Layout();
    EXPECT_FALSE(layoutWrapper->GetOrCreateChildByIndex(9, false)->IsActive());
    EXPECT_TRUE(layoutWrapper->GetOrCreateChildByIndex(0, false)->IsActive());
}

/**
 * @tc.name: GridTest019
 * @tc.desc: Test all the properties of grid.
 * @tc.type: FUNC
 */
HWTEST_F(GridPatternTestNg, GridTest019, TestSize.Level1)
{
    /**
     * @tc.steps: step1. create GridTestProperty and set properties of grid.
     */
    GridTestProperty gridTestProperty;
    gridTestProperty.rowsTemplate = std::make_optional("1fr 1fr 1fr");
    gridTestProperty.columnsTemplate = std::make_optional("1fr 1fr");
    gridTestProperty.rowsGap = std::make_optional(GRID_ROWS_GAP);
    gridTestProperty.columnsGap = std::make_optional(GRID_COLUMNS_GAP);
    gridTestProperty.cachedCount = std::make_optional(GRID_CACHED_COUNT);
    gridTestProperty.gridDirection = std::make_optional(FlexDirection::ROW);
    gridTestProperty.maxCount = std::make_optional(GRID_MAX_COUNT);
    gridTestProperty.minCount = std::make_optional(GRID_MIN_COUNT);
    gridTestProperty.cellLength = std::make_optional(GRID_CELL_LENGTH);
    gridTestProperty.editable = std::make_optional(true);
    gridTestProperty.scrollBarMode = std::make_optional(static_cast<int32_t>(NG::DisplayMode::ON));
    gridTestProperty.scrollBarWidth = std::make_optional(SCROLL_BAR_WIDTH);
    gridTestProperty.scrollBarColor = std::make_optional(SCROLL_BAR_COLOR);

    /**
     * @tc.steps: step2. create grid frameNode and get GridLayoutProperty.
     * @tc.expected: step2. get GridLayoutProperty success.
     */
    RefPtr<FrameNode> frameNode = CreateGrid(gridTestProperty);
    ASSERT_NE(frameNode, nullptr);
    auto layoutProperty = frameNode->GetLayoutProperty<GridLayoutProperty>();
    ASSERT_NE(layoutProperty, nullptr);

    /**
     * @tc.steps: step3. compare grid properties and expected value.
     * @tc.expected: step3. grid properties equals expected value.
     */
    EXPECT_EQ(layoutProperty->GetRowsTemplate(), "1fr 1fr 1fr");
    EXPECT_EQ(layoutProperty->GetColumnsTemplate(), "1fr 1fr");
    EXPECT_EQ(layoutProperty->GetRowsGap(), GRID_ROWS_GAP);
    EXPECT_EQ(layoutProperty->GetColumnsGap(), GRID_COLUMNS_GAP);
    EXPECT_EQ(layoutProperty->GetCachedCount(), GRID_CACHED_COUNT);
    EXPECT_EQ(layoutProperty->GetGridDirection(), FlexDirection::ROW);
    EXPECT_EQ(layoutProperty->GetMaxCount(), GRID_MAX_COUNT);
    EXPECT_EQ(layoutProperty->GetMinCount(), GRID_MIN_COUNT);
    EXPECT_EQ(layoutProperty->GetCellLength(), GRID_CELL_LENGTH);
    EXPECT_EQ(layoutProperty->GetEditable(), true);

    auto paintProperty = frameNode->GetPaintProperty<ScrollablePaintProperty>();
    ASSERT_NE(paintProperty, nullptr);
    EXPECT_EQ(paintProperty->GetScrollBarMode(), NG::DisplayMode::ON);
    EXPECT_EQ(paintProperty->GetScrollBarWidth(), StringUtils::StringToDimensionWithUnit(SCROLL_BAR_WIDTH));
    EXPECT_EQ(paintProperty->GetScrollBarColor(), Color::FromString(SCROLL_BAR_COLOR));

    /**
     * @tc.steps: step4. change grid row/column template properties to test illegal template.
     */
    gridTestProperty.rowsTemplate = std::make_optional(GRID_TEMPLATE_ILLEGAL);
    gridTestProperty.columnsTemplate = std::make_optional(GRID_TEMPLATE_ILLEGAL);

    /**
     * @tc.steps: step5. create grid frameNode and get GridLayoutProperty again.
     * @tc.expected: step5. get GridLayoutProperty success again.
     */
    frameNode = CreateGrid(gridTestProperty);
    ASSERT_NE(frameNode, nullptr);
    layoutProperty = frameNode->GetLayoutProperty<GridLayoutProperty>();
    ASSERT_NE(layoutProperty, nullptr);

    /**
     * @tc.steps: step6. compare grid properties and expected value after change.
     * @tc.expected: step6. grid properties equals expected value after change.
     */
    EXPECT_EQ(layoutProperty->GetRowsTemplate(), "");
    EXPECT_EQ(layoutProperty->GetColumnsTemplate(), "");
}

/**
 * @tc.name: GridTest020
 * @tc.desc: Test OnDirtyLayoutWrapperSwap function of grid.
 * @tc.type: FUNC
 */
HWTEST_F(GridPatternTestNg, GridTest020, TestSize.Level1)
{
    /**
     * @tc.steps: step1. Create grid.
    */
    GridModelNG grid;
    RefPtr<ScrollControllerBase> positionController = grid.CreatePositionController();
    RefPtr<ScrollProxy> scrollBarProxy = grid.CreateScrollBarProxy();
    grid.Create(positionController, scrollBarProxy);
    /**
     * @tc.steps: step2. Set grid properties.
     */
    grid.SetMultiSelectable(true);
    grid.SetSupportAnimation(true);
    grid.SetOnScrollToIndex([](const BaseEventInfo*) {});
    grid.SetOnItemDragStart([](const ItemDragInfo&, int32_t) {});
    grid.SetOnItemDragEnter([](const ItemDragInfo) {});
    grid.SetOnItemDragMove([](const ItemDragInfo&, int32_t, int32_t) {});
    grid.SetOnItemDragLeave([](const ItemDragInfo&, int32_t) {});
    grid.SetOnItemDrop([](const ItemDragInfo&, int32_t, int32_t, bool) {});

    /**
     * @tc.steps: step3. Get frameNode.
     * @tc.expected: step3. Check whether the updated properties and parameters are correct.
     */
    auto frameNode = AceType::DynamicCast<FrameNode>(ViewStackProcessor::GetInstance()->Finish());
    ASSERT_NE(frameNode, nullptr);
    auto pattern = frameNode->GetPattern<GridPattern>();
    ASSERT_NE(pattern, nullptr);
    EXPECT_TRUE(pattern->multiSelectable_);
    EXPECT_TRUE(pattern->supportAnimation_);
    auto eventHub = frameNode->GetEventHub<GridEventHub>();
    ASSERT_NE(eventHub, nullptr);
    EXPECT_NE(eventHub->onScrollToIndex_, nullptr);
    EXPECT_NE(eventHub->onItemDragStart_, nullptr);
    EXPECT_NE(eventHub->onItemDragEnter_, nullptr);
    EXPECT_NE(eventHub->onItemDragMove_, nullptr);
    EXPECT_NE(eventHub->onItemDragLeave_, nullptr);
    EXPECT_NE(eventHub->onItemDrop_, nullptr);
}

/**
 * @tc.name: GridTest021
 * @tc.desc: Test all the properties of gridItem.
 * @tc.type: FUNC
 */
HWTEST_F(GridPatternTestNg, GridTest021, TestSize.Level1)
{
    /**
     * @tc.steps: step1. Create gridItem and Set properties.
    */
    GridItemModelNG gridItem;
    gridItem.Create([](int32_t) {}, false);
    gridItem.SetRowStart(1);
    gridItem.SetRowEnd(2);
    gridItem.SetColumnStart(1);
    gridItem.SetColumnEnd(2);
    gridItem.SetForceRebuild(true);
    gridItem.SetSelectable(false);
    gridItem.SetOnSelect([](bool) {});

    /**
     * @tc.steps: step2. Get frameNode and properties.
     * @tc.expected: step2. Check properties is correct.
    */
    auto frameNode = AceType::DynamicCast<FrameNode>(ViewStackProcessor::GetInstance()->Finish());
    ASSERT_NE(frameNode, nullptr);
    auto layoutProperty = frameNode->GetLayoutProperty<GridItemLayoutProperty>();
    ASSERT_NE(layoutProperty, nullptr);
    EXPECT_EQ(layoutProperty->GetRowStart(), 1);
    EXPECT_EQ(layoutProperty->GetRowEnd(), 2);
    EXPECT_EQ(layoutProperty->GetColumnStart(), 1);
    EXPECT_EQ(layoutProperty->GetColumnEnd(), 2);
    auto pattern = frameNode->GetPattern<GridItemPattern>();
    ASSERT_NE(pattern, nullptr);
    EXPECT_TRUE(pattern->forceRebuild_);
    EXPECT_FALSE(pattern->selectable_);
    auto eventHub = frameNode->GetEventHub<GridItemEventHub>();
    ASSERT_NE(eventHub, nullptr);
    EXPECT_NE(eventHub->onSelect_, nullptr);
}
} // namespace OHOS::Ace::NG
